#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

//1

//int main()
//{
//	printf("%o\n", 20);//%o以八进制打印
//	printf("%x\n", 16);//%x以十六进制打印
//	printf("%d\n", 31);//%d就以十进制打印出来
//	//       写的数字默认十进制
//	printf("%d\n", 153);
//	printf("%d\n", 0153);
//	           //区出八进制，表明八进制
//	printf("%d\n", 0x12);//前缀0x十六进制
//	//1-1;
//	//1+(-1)
//	//尝试用原码计算
//	//0 000000000000000000000000000000 1  -- 1的原码
//	//1 000000000000000000000000000000 1  -> -1的原码
//	//10000000000000000000000000000010 -> -2 //err
//	//用补码计算
//	//00000000000000000000000000000001 -- 1的补码
//	//11111111111111111111111111111111 -> -1的补码
//	//100000000000000000000000000000000  //多的1去掉
//	//00000000000000000000000000000000 -- 0
//所以运算用补码运算
//	return 0;
//}

//2 移位操作符

//int main()
//{
//	int a = 10;
//	int b = a + 1;
//	//b=11
//	//a=10
//	int c = 10;
//	int d = c << 1;
//	printf("c=%d\n", c);
//	printf("d=%d\n", d);
//	//自己真变
//	c = c << 1;//c <<= 1
//	printf("c=%d\n", c);
//
//	//左移
//	int e = -1;
//	int f = e << 1;
//	//10000000000000000000000000000001
//	//11111111111111111111111111111111 -> -1的补码
//	//11111111111111111111111111111110 -- 对-1的补码动后
//	//
//	//11111111111111111111111111111110 -- f补码接-1动后补码
//	//要看显出来的数字多少要等换到原码算
//	//10000000000000000000000000000010 -- 现在f的原码
//	//等于-2
//	//左移一位数字踏0左移一位加的每位数字乘的权重加1，这里相当于整体乘2
//	printf("e=%d\n", e);
//	printf("f=%d\n", f);
//
//	//右移
//	int g = -10;
//	//11111111111111111111111111110111 -- 补码
//	int h = g >> 1;//算术右移
//	//11111111111111111111111111111011 -- 右移后补码
//	//10000000000000000000000000000101 -- 右移后原码
//	printf("g=%d\n", g);//-10
//	printf("h=%d\n", h);//-5
//	//右移一位除2效果
//	return 0;
//}

//3 位操作符

//int main()
//{
//	int a = 6;
//	//00000000000000000000000000000110 -- 6的原、反、补相同
//	int b = -7;
//	//11111111111111111111111111111001 -> -7的补码
//	 
//	 
//	//按位与&操作符：
//	int c = a & b;//a和b的补码的二进制位进行运算
//	//规则：对应的二进制位，有0则为0，两个同时为1，才为1
//	// 
//	//00000000000000000000000000000110 -- 6的补码
//	//11111111111111111111111111111001 -> -7的补码
//	//00000000000000000000000000000000 -- 0的反码、补码都是自己0 -- c=0
//	printf("c=%d\n", c);
//
//
//	//按位或|操作符：
//	int d = a | b;//a和b的补码的二进制位进行运算
//	//规则：只要有1，就是1，两个同时为0，才为0
//	// 
//	//00000000000000000000000000000110 -- 6的补码
//	//11111111111111111111111111111001 -> -7的补码
//	//11111111111111111111111111111111 -- d的补码
//	//10000000000000000000000000000001 -- d的原码 -- d=-1
//	printf("d=%d\n", d);
//
//	//按位异或^：
//	int e = a ^ b;//a和b的补码的二进制位进行运算
//	//规则：对应的二进制位，相同为0，相异为1
//	//
//	//00000000000000000000000000000110 -- 6的补码
//	//11111111111111111111111111111001 -> -7的补码
//	//11111111111111111111111111111111 -- e的补码
//	//10000000000000000000000000000001 -- e的原码 -- e=-1
//	printf("e=%d\n", e);
//
//	//&、|、^都是双目操作符
//	//~单目操作符
//
//	//按位取反
//	int f = 0;
//	printf("~f=%d\n", ~f);
//	//规则：按(2进制)位取反，原来是0的变1，原来是1的变0
//	//00000000000000000000000000000000 -- 0的补码
//	//11111111111111111111111111111111 -- ~f的补码
//	//10000000000000000000000000000000
//	//10000000000000000000000000000001 -- ~f的原码 -- ~f=-1
//	return 0;
//}

//4  不能创建临时变量（第三个变量），实现两个整数的交换

//int main()
//{
//	int a = 3;
//	int b = 5;
//	printf("交换前：a=%d,b=%d\n", a, b);
//	//a = a + b;//但加、减起来就有原本int里放的a、b没事，它们的和差之后超出整形范围的可能
//	//b = a - b;
//	//a = a - b;
//	a = a ^ b;
//	b = a ^ b;
//	a = a ^ b;
//	printf("交换后：a=%d,b=%d\n", a, b);
//	return 0;
//}

//5 算数的二进制形式里1的个数

//int count_bit_one(unsigned int n)//n为正数的话算出来的1的个数与实际32位里1的个数一样的，负数的话就不会一样了
//{
//	int count = 0;
//	while (n)
//	{
//		if ((n % 2) == 1)
//			count++;
//		n = n / 2;
//	}
//	return count;
//}
//
//int main()
//{
//	int num = 0;
//	scanf("%d", &num);//num输入-1
//	int ret = count_bit_one(num);
//	printf("%d\n", ret);
//	return 0;
//}

//6

//void text() 
//{
//	printf("hehe\n");
//}
//int main()
//{
//	text();
//	return 0;
//}
////err
////得放前面
////void text()
////{
////	printf("hehe\n");
////}

//7 算数的二进制形式里1的个数

//int count_bit_one(int n)
//{
//	int i = 0;
//	int count = 0;
//	for (i = 0;i < 32;i++)
//	{
//		if (((n >> i) & 1) == 1)
//		{
//			count++;
//		}
//	}
//	return count;
//}
//
//int main()
//{
//	int num = 0;
//	scanf("%d", &num);
//	int ret = count_bit_one(num);
//	printf("%d\n", ret);
//	return 0;
//}

//8 判断n是否是2的次方数

//int main()
//{
//	int n = 0;
//	scanf("%d", &n);
//	if ((n & (n - 1)) == 0)
//		printf("n是2的次方数\n");
//	return 0;
//}

//9  编写代码将13二进制序列的第5位修改为1，然后再改回0
//                             n

////位操作符、移位操作符这里都是对正数了，正数的补码=原码
//int main()
//{
//	int a = 13;
//	//00000000000000000000000000001101 -- 13补码(原码)
//	//00000000000000000000000000010000 -- 按位或上去
//	//00000000000000000000000000000001 -- 1往左移n-1位
//	int n = 5;
//	a = (1 << (n - 1)) | a;//a |= (1 << (n - 1));
//	printf("%d\n", a);
//	//00000000000000000000000000011101 -- 改后a
//	//11111111111111111111111111101111 -- 按位与上去
//	//00000000000000000000000000010000 -- 它取反上去得到
//	//00000000000000000000000000000001 -- 还是1往左移n-1位
//	a &= ~(1 << n - 1);//a = a & ~(1 << n - 1);
//	printf("%d\n", a);
//	return 0;
//}


//10 逗号表达式


//(1)

//int main()
//{
//	int a = 1;
//	int b = 2;
//	int c = (a > b, a = b + 10, a, b = a + 1);//逗号表达式
//	//         0      12       12     13
//	printf("%d\n", c);//c=最后一个表达式的值13
//	return 0;
//}


//(2)

//int main()
//{
//	int a = 0;
//	int b = 0;
//	int c = 0;
//	int d = 0;
//	if (a = b + 1, c = a / 2, d > 0)
//	{//d=0不大于0，d>0表达式为假出0值
//		printf("hehe\n");
//	}
//	return 0;
//}


//(3)

////算、判断、{做}——>算、判断、{做}——>算、判断……
//int get_yal()
//{
//	return 0;
//}
//int count_val(int a)
//{
//
//}
//int main()
//{
//	int a = 0;
//
//	a = get_yal();//算
//	count_val(a);
//
//	while (a > 0)//判断
//	{
//	//业务处理  //做
//	//……
//
//	a = get_yal();//算
//	count_val(a);
//
//	}
//	return 0;
//}


//(4)

////优化
//int get_yal()
//{
//	return 0;
//	//它如果不写return，返回类型那边写了不是不返回值(viod)，而是返回一个整形，它就会返回一个整形，一个随机的，while循环就一直进，直到随机值<=0为止
//}
//int count_val(int a)
//{
//	
//}
//int main()
//{
//	int a = 0;//         算             判断
//	printf("hehe\n");
//	while (a = get_yal(), count_val(a), a > 0)
//	{
//		//业务处理   //做
//		//……
//	}
//	return 0;
//}


//11 函数没有return也行


//int text()
//{
//	printf("hehe\n");
//}
//int main()
//{
//	printf("hehe\n");
//	int b = text(4);
//	printf("%d\n", b);
//}


//12 []下标引用操作符
//    (索引)


//int main()
//{
//	int arr[10] = { 1,2,3,4,5 };
//	int m = arr[4];//arr数组中下标是4的元素
//	//[] 下标引用操作符 - 操作数是 :arr,4
//	//双目操作符，数组名、下标(索引)
//	printf("%d\n", m);
//	return 0;
//}


//13 ()函数调用操作符

//int Add(int x, int y)
//{
//	return x + y;
//}
//void text()
//{
//
//}
//int main()
//{
//	printf("hehe\n");//()就是函数调用操作符，操作数是printf、"hehe\n"
//	printf("%d\n", 100);
//	int ret = Add(3, 5);//3个操作数—Add、3、5
//	text();//()至少函数名一个操作数，可以不传参
//	return 0;
//}


//14 结构体变量


////结构的声明在外面
////学生类型
//struct Student
//{
//	//成员变量(至少一个),成员变量放一起成成员列表
//	char name[20];
//	int age;            //模具，里面不存放数据,类型+变量名
//	float score;
//}s4={"王五",16,86.0}, s5, s6;//变量列表，这里创建的变量是全局变量
//struct Point
//{
//	int x;
//	int y;
//};
//struct S
//{
//	char ch;
//	struct Point p;
//	int arr[10];
//	double d;
//};
//
//int main()
//{//已是一种变量类型，类型来创建变量 //int a;
//	struct Student s1 = { "张三",20,98.0 };//局部变量
//	struct Student s2 = { "李四",18,69.8 };//结构体类型创建结构体变量，在这里存放我们的数据
//	struct Point p = { 10,20 };
//	struct S s = { 'a',{4,5},{1,2,3,4,5,6,7},3.14 };//同类型同结构不同变量    int a ; int b ; 之前是没什么结构概念
//	//变量里面是值——>变量里面是再变量再是值   变量与值挂钩
//	struct S s3 = { 'b',{5,6},{2,3,4,5,6,7,8,},3.24 };
//	printf("变量s里面的字符变量ch里的值是%c\n", s.ch);
//	printf("s里存放的坐标是%d,%d\n", s.p.x, s.p.y);
//	printf("变量s里的变量数组arr[0]存放的值是%d \n变量s里的变量浮点型d里存放的值是%lf\n", s.arr[0],s.d);
//	//结构成员访问操作符
//	//   .   结构体变量.成员名
//  //   ->  结构体指针->成员名
//	return 0;
//}
//
//struct Stu
//{
//	char name[20];//字符数组可用"单个字符们合成的字符串"、{'单个字符','单个字符'}初始化
//	int age;
//};
//int main()
//{
//	struct Stu s = { "zhangsan",20 };
//	printf("%s %d\n", s.name, s.age);
//	struct Stu* p = &s;
//	printf("%s %d\n", (*p).name, (*p).age);
//	printf("%s %d\n", p->name, p->age);
//	return 0;     //包括解引用
//}


//15 运算优先级


//int main()
//{//相邻的操作符才讨论优先级的
//	int r = 3 + 4 * 5;//相邻的操作符，优先级高的先执行
//	int a = 3 + 4 + 5;//相邻的操作符的优先级相同的情况下，结合性说的算
//	return 0;
//}


//16 整型提升


//int main()
//{
//	//本来就是整型，就不用整型提升，整型提升针对字符和短整型提升到整型
//	int d = 10;
//	int e = 20;
//	int f = d + e;
//
//	char a = 20;
//	//00000000000000000000000000010100 - a原码等于补码
//	//00010100 - a  //char变量只能存八个比特位  //char a符号位为0
//
//	char b = 130;
//	//00000000000000000000000010000010
//	//10000010 - b  //char b符号位为1
//
//	//遇到运算符要用CPU时(CPU只能操作整形)，运算之前要先把a、b提升为整形类型的值，提升的过程被称为整型提升
//	char c = a + b;//补符号位到int32位才送到CPU相加，补也是对补码
//	//000000000000000000000000 00010100 - 补好后a
//	//111111111111111111111111 10000010 - 补好后b
//	//111111111111111111111111 10010110 - a+b和后c的补码
//	//10010110 - 截取八位放，char c 补码
//
//	printf("%d\n", c);//%d打印有符号的整数，要整型，对char c也要整型提升
//	//111111111111111111111111 10010110 - 对char c补码补完后的补码
//	//100000000000000000000000 01101001
//	//100000000000000000000000 01101010 - 补完后c的原码，看出即-106
//	return 0;
//}


//17


// struct Student
// {
// 	char name[20];
// 	int age;
// 	float score;
// };//其实这里就是类型，struct Student 缩点也是类型


//18


//一个整型4个字节，一个字节8个bit位，一个二进制数一个bit位
//-4
//10000000000000000000000000000100 --原码，原码变补码取反+1
//11111111111111111111111111111011 --反码
//11111111111111111111111111111100 --补码，补码变为原码也是取反+1，就不用-1取反了

//二进制转十六进制4个二进制数转1个十六进制数
//11111111111111111111111111111100 == 0xFFFFFFFC
//这个二进制数转十进制数的话会是个很大的数 == 4294967292

//内存里存值、运算以数值的补码形式，显示时以数值的原码显示
//正数的原反补码都相同，负数的就要动转化



//int main()
//{//正数原反补码都是原码本身一样，负数的取反与+1转化
//	printf("%d\n", -4);//打印时，会区分正负数的根据数值正负以相应方式转为其原码显示  %d
//	printf("%p\n", -4);//不存在正负概念的补码转原码等于转用  %p
//	printf("%u\n", -4);
//	return 0;
//}